<template>
    <div class="wrapper">
        <div id="container" ref="container"></div>
        <div class="btn-list">
            <button class="btn" @click="addNode">add</button>
            <button class="btn" @click="formatGraph">格式化</button>
        </div>
    </div>
</template>

<script>
import { Graph } from "@antv/x6";
import { DagreLayout } from "@antv/layout";

export default {
    name: "",
    data () {
        return {
            graph: null,
            nodes: [],
            edges: [],
            node_width: 100,
            node_height: 30,
            mock_data: {},
            TaskEdge: null,
            direction: "TB"
        };
    },
    methods: {
        // 初始化Graph
        initGraph () {
            // 初始化graph
            this.graph = new Graph({
                container: this.$refs.container,
                width: 1300,
                height: 800,
                background: {
                    color: "#fffbe6"
                },
                grid: {
                    size: 10,
                    visible: true
                },
                panning: {
                    enabled: true
                },
                connecting: {
                    allowMulti: "withPort"
                }
            });

            // 注册一些事件
            this.registEvents();
            // 渲染节点和边
            this.mock_data.nodeDataArray.forEach(item => {
                this.addNode(item);
            });
            this.mock_data.linkDataArray.forEach(item => {
                this.addEdge(item);
            });
        },
        // 新增节点
        addNode (cfg) {
            const rect = this.graph.addNode({
                id: cfg.id || 0,
                x: cfg.x || 0,
                y: cfg.y || 0,
                width: this.node_width,
                height: this.node_height,
                label: cfg.id || "no label",
                attrs: {
                    body: {
                        fill: "#f5f5f5",
                        stroke: "#d9d9d9",
                        strokeWidth: 1
                    },
                    label: {
                        fontSize: 12
                    }
                },
                ports: {
                    groups: {
                        top: {
                            attrs: {
                                circle: {
                                    magnet: true,
                                    r: 3,
                                    stroke: "#31d0c6",
                                    strokeWidth: 2,
                                    fill: "#fff",
                                    style: {
                                        visibility: "hidden"
                                    }
                                }
                            },
                            position: {
                                name: "top"
                            }
                        },
                        right: {
                            attrs: {
                                circle: {
                                    magnet: true,
                                    r: 3,
                                    stroke: "#31d0c6",
                                    strokeWidth: 2,
                                    fill: "#fff",
                                    style: {
                                        visibility: "hidden"
                                    }
                                }
                            },
                            position: {
                                name: "right"
                            }
                        },
                        bottom: {
                            attrs: {
                                circle: {
                                    magnet: true,
                                    r: 3,
                                    stroke: "#31d0c6",
                                    strokeWidth: 2,
                                    fill: "#fff",
                                    style: {
                                        visibility: "hidden"
                                    }
                                }
                            },
                            position: {
                                name: "bottom"
                            }
                        },
                        left: {
                            attrs: {
                                circle: {
                                    magnet: true,
                                    r: 3,
                                    stroke: "#31d0c6",
                                    strokeWidth: 2,
                                    fill: "#fff",
                                    style: {
                                        visibility: "hidden"
                                    }
                                }
                            },
                            position: {
                                name: "left"
                            }
                        }
                    },
                    items: [
                        { id: "top", group: "top" },
                        { id: "right", group: "right" },
                        { id: "bottom", group: "bottom" },
                        { id: "left", group: "left" }
                    ]
                }
            });
            this.nodes.push(rect);
        },
        // 新增边
        addEdge (cfg) {
            this.graph.addEdge({
                id: cfg.id,
                source: cfg.source,
                target: cfg.target,
                router: {
                    name: "manhattan",
                    args: {
                        padding: 20
                    }
                }
            });
        },
        // 注册一些事件
        registEvents () {
            // 显示/隐藏事件
            const showPorts = (ports, show) => {
                for (let i = 0, len = ports.length; i < len; i++) {
                    ports[i].style.visibility = show ? "visible" : "hidden";
                }
            };
            // 鼠标移入，显示连接桩
            this.graph.on("node:mouseenter", () => {
                const ports = this.$refs.container.querySelectorAll(".x6-port-body");
                showPorts(ports, true);
            });
            // 鼠标移出，隐藏连接桩
            this.graph.on("node:mouseleave", () => {
                const ports = this.$refs.container.querySelectorAll(".x6-port-body");
                showPorts(ports, false);
            });
        },
        // 格式化
        formatGraph () {
            this.direction = this.direction === "TB" ? "LR" : "TB";
            let config = {
                ranksep: 40,
                nodesep: 25
            };
            if (this.direction === "LR") {
                config = {
                    ranksep: 50,
                    nodesep: 15
                };
            }
            const dagreLayout = new DagreLayout({
                type: "dagre",
                rankdir: this.direction,
                ...config
            });

            const nodesArr = this.graph.getNodes();
            const nodes = nodesArr.map(node => ({
                id: node.id,
                label: node.label
            }));
            const edges = this.graph.getEdges();
            const model = dagreLayout.layout({ nodes, edges });
            nodesArr.forEach(item => {
                const node = model.nodes.find(val => val.id === item.id);
                if (node) {
                    const { x, y } = node;
                    item.position(x, y);
                }
            });
            const cellArr = this.graph.getCells();
            cellArr.forEach(cell => {
                const edgeView = this.graph.findViewByCell(cell);
                edgeView.update();
            });
        },
        // 构造数据
        mockData () {
            this.mock_data = {
                nodeDataArray: [
                    { id: "node1", x: 100, y: 50 },
                    { id: "node2", x: 110, y: 60 },
                    { id: "node3", x: 120, y: 70 },
                    { id: "node4", x: 130, y: 80 },
                    { id: "node5", x: 140, y: 90 },
                    { id: "node6", x: 150, y: 100 },
                    { id: "node7", x: 160, y: 110 },
                    { id: "node8", x: 170, y: 120 },
                    { id: "node9", x: 180, y: 130 },
                    { id: "node10", x: 190, y: 140 }
                ],
                linkDataArray: [
                    { id: "1-2", source: "node1", target: "node2" },
                    { id: "1-3", source: "node1", target: "node3" },
                    { id: "1-4", source: "node1", target: "node4" },
                    { id: "1-5", source: "node1", target: "node5" },
                    { id: "1-6", source: "node1", target: "node6" },
                    { id: "1-7", source: "node1", target: "node7" },
                    { id: "1-8", source: "node1", target: "node8" },
                    { id: "9-10", source: "node9", target: "node10" }
                ]
            };
        }
    },
    created () {},
    mounted () {
        this.mockData();
        this.initGraph();
    }
};
</script>

<style scoped>
.wrapper {
    display: flex;
}
.btn-list {
    margin: 0 0 0 10px;
}
.btn {
    display: block;
    width: 50px;
    height: 20px;
    margin: 0 0 10px 0;
}
</style>
